package com.bonc.modules.dial.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bonc.datasource.annotation.DataSource;
import com.bonc.modules.dial.dao.ServDialTestInfoMonDao;
import com.bonc.modules.dial.entity.ServDialTestInfoMon;
import com.bonc.modules.dial.param.ServDialTestInfoMonParam;
import com.bonc.modules.dial.result.DialResult;
import com.bonc.modules.dial.result.DialResultY;
import com.bonc.modules.dial.service.ServDialTestInfoMonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

@DataSource("data")
@Service
public class ServDialTestInfoMonServiceImpl extends ServiceImpl<ServDialTestInfoMonDao, ServDialTestInfoMon> implements ServDialTestInfoMonService {

    @Autowired
    private ServDialTestInfoMonDao servDialTestInfoMonDao;

    private List<String> createDealDateList(String beginDateStr, String endDateStr){
        DateTimeFormatter destFormat = DateTimeFormatter.ofPattern("yyyyMM");
        DateTimeFormatter srcFormat = new DateTimeFormatterBuilder()
                .appendPattern("yyyy-MM")
                .parseDefaulting(ChronoField.DAY_OF_MONTH, 1)
                .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
                .toFormatter();
        LocalDateTime localDateTimeBegin = LocalDateTime.parse(beginDateStr, srcFormat);
        LocalDateTime localDateTimeEnd   = LocalDateTime.parse(endDateStr,   srcFormat);
        List<String> result = new ArrayList<>();
        for(LocalDateTime localDateTimeTmp = localDateTimeBegin;
            localDateTimeTmp.compareTo(localDateTimeEnd) <= 0;
            localDateTimeTmp = localDateTimeTmp.plus(1, ChronoUnit.MONTHS)){
            result.add(localDateTimeTmp.format(destFormat));
        }
        return result;
    }

    private List<DialResult> convertDialStat(List<ServDialTestInfoMon> servDialTestInfoMonList, List<String> dealDateList){
        List<DialResult> dialResultList = new ArrayList<>();
        Map<String, Map<String, Map<String, List<ServDialTestInfoMon>>>> resultMap = new HashMap<>();
        for(ServDialTestInfoMon servDialTestInfoMon : servDialTestInfoMonList){
            Map<String, Map<String, List<ServDialTestInfoMon>>> map1 = resultMap.get(servDialTestInfoMon.getItemName());
            Map<String, List<ServDialTestInfoMon>> map2 = null;
            List<ServDialTestInfoMon> list = null;

            if(null == map1){
                list = new ArrayList<ServDialTestInfoMon>();
                map2 = new HashMap<String, List<ServDialTestInfoMon>>();
                map2.put(servDialTestInfoMon.getNetworkFlag(), list);
                map1 = new HashMap<String, Map<String, List<ServDialTestInfoMon>>>();
                map1.put(servDialTestInfoMon.getProdtCode(), map2);
                resultMap.put(servDialTestInfoMon.getItemName(), map1);
            } else {
                map2 = map1.get(servDialTestInfoMon.getProdtCode());
                if(map2 == null){
                    list = new ArrayList<ServDialTestInfoMon>();
                    map2 = new HashMap<String, List<ServDialTestInfoMon>>();
                    map2.put(servDialTestInfoMon.getNetworkFlag(), list);
                    map1.put(servDialTestInfoMon.getProdtCode(), map2);
                } else {
                    list = map2.get(servDialTestInfoMon.getNetworkFlag());
                    if(list == null){
                        list = new ArrayList<ServDialTestInfoMon>();
                        map2.put(servDialTestInfoMon.getNetworkFlag(), list);
                    }
                }
            }

            resultMap.get(servDialTestInfoMon.getItemName()).get(servDialTestInfoMon.getProdtCode()).get(servDialTestInfoMon.getNetworkFlag()).add(servDialTestInfoMon);
        }
        Iterator<String> iterator = resultMap.keySet().iterator();
        while(iterator.hasNext()){
            DialResult dialResult = new DialResult();
            for(int i = 0; i < dealDateList.size(); i++){
                dialResult.getXAxis().add(dealDateList.get(i));
            }
            Map<String, Map<String, List<ServDialTestInfoMon>>> map1 = resultMap.get(iterator.next());
            Iterator<String> iterator1 = map1.keySet().iterator();
            while(iterator1.hasNext()){
                Map<String, List<ServDialTestInfoMon>> map2 = map1.get(iterator1.next());
                Iterator<String> iterator2 = map2.keySet().iterator();
                while(iterator2.hasNext()){
                    List<ServDialTestInfoMon> list = map2.get(iterator2.next());
                    Map<String, ServDialTestInfoMon> itemResultMap = list.stream().collect(Collectors.toMap(ServDialTestInfoMon::getDealDate, servDialTestInfoMon -> servDialTestInfoMon));
                    DialResultY dialResultY = new DialResultY();
                    for(int i = 0; i < dealDateList.size(); i++){
                        ServDialTestInfoMon servDialTestInfoMon = itemResultMap.get(dealDateList.get(i));
                        if(ObjectUtil.isNotEmpty(servDialTestInfoMon) && ObjectUtil.isNotEmpty(servDialTestInfoMon.getItemValue())){
                            dialResultY.getData().add(servDialTestInfoMon.getItemValue().toString());
                        } else {
                            dialResultY.getData().add("");
                        }
                        if(ObjectUtil.isNotEmpty(servDialTestInfoMon) && ObjectUtil.isNotEmpty(servDialTestInfoMon.getTtemNum())){
                            dialResultY.getDialCnt().add(servDialTestInfoMon.getTtemNum());
                        } else {
                            dialResultY.getDialCnt().add(0);
                        }

                        if(ObjectUtil.isEmpty(dialResultY.getNetworkFlag()) && ObjectUtil.isNotEmpty(servDialTestInfoMon) && ObjectUtil.isNotEmpty(servDialTestInfoMon.getNetworkFlag())){
                            dialResultY.setNetworkFlag(servDialTestInfoMon.getNetworkFlag());
                        }
                        if(ObjectUtil.isEmpty(dialResultY.getProdtName()) && ObjectUtil.isNotEmpty(servDialTestInfoMon) && ObjectUtil.isNotEmpty(servDialTestInfoMon.getProdtName())){
                            dialResultY.setProdtName(servDialTestInfoMon.getProdtName());
                        }
                        if(ObjectUtil.isEmpty(dialResult.getItemName()) && ObjectUtil.isNotEmpty(servDialTestInfoMon) && ObjectUtil.isNotEmpty(servDialTestInfoMon.getItemName())){
                            dialResult.setItemName(servDialTestInfoMon.getItemName());
                        }
                    }
                    dialResult.getYAxis().add(dialResultY);
                }
            }
            dialResultList.add(dialResult);
        }
        return dialResultList;
    }

    @Override
    public List<DialResult> dialTestStat(ServDialTestInfoMonParam servDialTestInfoMonParam){
        LambdaQueryWrapper<ServDialTestInfoMon> queryWrapper = new LambdaQueryWrapper<>();

        List<String> dealDateList = new ArrayList<String>();
        if(ObjectUtil.isNotEmpty(servDialTestInfoMonParam.getBeginDate()) && ObjectUtil.isNotEmpty(servDialTestInfoMonParam.getEndDate())){
            dealDateList = createDealDateList(servDialTestInfoMonParam.getBeginDate(), servDialTestInfoMonParam.getEndDate());
        }
        if(ObjectUtil.isNotEmpty(dealDateList)){
            queryWrapper.in(ServDialTestInfoMon::getDealDate, dealDateList);
        }
        // 产品名称
        if(ObjectUtil.isNotEmpty(servDialTestInfoMonParam.getProdtCode())){
            queryWrapper.eq(ServDialTestInfoMon::getProdtCode, servDialTestInfoMonParam.getProdtCode());
        }
        // 指标
        if(ObjectUtil.isNotEmpty(servDialTestInfoMonParam.getItemCodeList())){
            queryWrapper.in(ServDialTestInfoMon::getItemCode, servDialTestInfoMonParam.getItemCodeList());
        }
        // 网络类型
        if(ObjectUtil.isNotEmpty(servDialTestInfoMonParam.getNetworkFlag())){
            queryWrapper.eq(ServDialTestInfoMon::getNetworkFlag, servDialTestInfoMonParam.getNetworkFlag());
        }
        List<ServDialTestInfoMon> servDialTestInfoMonList = baseMapper.selectList(queryWrapper);

        return convertDialStat(servDialTestInfoMonList, dealDateList);
    }

    @Override
    public List<DialResult> competingProStat(ServDialTestInfoMonParam servDialTestInfoMonParam){
        LambdaQueryWrapper<ServDialTestInfoMon> queryWrapper = new LambdaQueryWrapper<>();

        List<String> dealDateList = new ArrayList<String>();
        if(ObjectUtil.isNotEmpty(servDialTestInfoMonParam.getBeginDate()) && ObjectUtil.isNotEmpty(servDialTestInfoMonParam.getEndDate())){
            dealDateList = createDealDateList(servDialTestInfoMonParam.getBeginDate(), servDialTestInfoMonParam.getEndDate());
        }
        if(ObjectUtil.isNotEmpty(dealDateList)){
            servDialTestInfoMonParam.setDealDateList(dealDateList);
        }

        List<ServDialTestInfoMon> servDialTestInfoMonList = servDialTestInfoMonDao.competingProStat(servDialTestInfoMonParam);
        return convertDialStat(servDialTestInfoMonList, dealDateList);
    }
}
